Skip to content

New function pointer APIs#123819

Open
jgh07 wants to merge 39 commits intodotnet:mainfrom
jgh07:issue-75348
Open

New function pointer APIs#123819
jgh07 wants to merge 39 commits intodotnet:mainfrom
jgh07:issue-75348

Conversation

@jgh07
Copy link
Contributor

@jgh07 jgh07 commented Jan 30, 2026

This implements #75348.

MakeFunctionPointerType is only implemented for CoreCLR, a Mono implementation will follow.

Copilot AI review requested due to automatic review settings January 30, 2026 22:34
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jan 30, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-reflection
See info in area-owners.md if you want to be subscribed.

public abstract void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes);

/// <summary>
/// Puts a <see cref="OpCodes.Calli"/> instruction onto the Microsoft intermediate language (MSIL) stream,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept this description largely the same as the existing overloads. I think it might make more sense to update it though, since as far as I'm concerned the term MSIL was dropped in favor of CIL.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements new function pointer APIs as proposed in issue #75348, enabling better support for function pointer types in IL generation and reflection scenarios.

Changes:

  • Adds Type.MakeFunctionPointerSignatureType and Type.MakeModifiedSignatureType static factory methods for creating signature types
  • Implements ILGenerator.EmitCalli(Type functionPointerType) overload in ILGeneratorImpl for modern function pointer calling conventions
  • Adds new internal SignatureFunctionPointerType and SignatureModifiedType classes to represent these signature types

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
System.Runtime.cs Adds public API surface for new function pointer and modified signature type factory methods
Type.cs Implements MakeFunctionPointerSignatureType and MakeModifiedSignatureType factory methods with XML documentation
SignatureFunctionPointerType.cs New internal class representing function pointer signature types with support for calling conventions
SignatureModifiedType.cs New internal class representing types with required/optional custom modifiers
SignatureType.cs Changes UnderlyingSystemType from sealed to virtual to allow SignatureModifiedType to override it
ILGenerator.cs Adds new EmitCalli overload accepting function pointer Type with XML documentation
ILGeneratorImpl.cs Implements the new EmitCalli overload with stack tracking and signature token generation
SignatureHelper.cs Makes WriteSignatureForFunctionPointerType internal and adds logic to unwrap SignatureTypes
ModuleBuilderImpl.cs Adds GetFunctionPointerSignatureToken method to generate standalone signatures for calli instructions
DynamicILGenerator.cs Adds stub TODO implementation for EmitCalli - not yet functional
System.Reflection.Emit.ILGeneration.cs Adds public API surface for new EmitCalli overload
Strings.resx Adds error message for invalid function pointer type arguments
System.Private.CoreLib.Shared.projitems Adds new SignatureFunctionPointerType and SignatureModifiedType to project, plus unrelated whitespace fix
SignatureTypes.cs Adds tests for the new MakeFunctionPointerSignatureType and MakeModifiedSignatureType methods
AssemblySaveILGeneratorTests.cs Adds end-to-end test for EmitCalli with function pointer types
Utilities.cs Adds ClassWithFunctionPointer test helper class
Comments suppressed due to low confidence (1)

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs:6

  • This using directive appears to be unused. There are no references to System.IO types in this file. Consider removing it to keep the code clean.
using System.Reflection.Metadata;

Copilot AI review requested due to automatic review settings February 2, 2026 13:32
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 7 comments.

Copilot AI review requested due to automatic review settings February 2, 2026 17:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.


for (int i = 0; i < parameterTypes.Length; i++)
{
ArgumentNullException.ThrowIfNull(parameterTypes[i], nameof(parameterTypes));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to allow void as parameter type?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Or uninstantiated generic type definitions.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not, I'll add checks for those.

{
Debug.Assert(type != null);

if (type.IsFunctionPointer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see why we are special casing function pointer here. Should it be handled by AddOneArgTypeHelper instead?

If there is a non-obvious reason for this special case, comment would be nice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it to AddOneArgTypeHelper.

if (t.ContainsGenericParameters)
throw new ArgumentException(SR.Argument_GenericsInvalid, nameof(requiredCustomModifiers));

AddElementType((CorElementType)0x22); // ELEMENT_TYPE_CMOD_INTERNAL
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why we cannot use the ELEMENT_TYPE_CMOD_OPT/ELEMENT_TYPE_CMOD_REQD encoding that's used for arguments in AddDynamicArgument? It looks odd that argument types and return types use different encoding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only reason was that at the start I wanted to avoid adding a DynamicScope parameter. I've cleaned it up now.

}
}
else if (clsArgument.IsFunctionPointer && scope != null)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we throw NotSupportedException for scope == null? It is better to throw than produce bad binary silently.

I assume that it can be hit with (non-persistent) Reflection.Emit. Is that right? We may want to add a test that validates it is throwing (and not crashing or producing bad output).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that it can be hit with (non-persistent) Reflection.Emit. Is that right?

Yes, or by just invoking SignatureHelper manually. I added an exception.

Copilot AI review requested due to automatic review settings February 15, 2026 18:26
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 30 out of 30 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings February 15, 2026 18:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 30 out of 30 changed files in this pull request and generated 3 comments.

Copilot AI review requested due to automatic review settings February 15, 2026 20:00
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 30 out of 30 changed files in this pull request and generated 1 comment.


public override Type MakeFunctionPointerType(Type[]? parameterTypes, bool isUnmanaged = false)
{
return Type.MakeFunctionPointerSignatureType(this, parameterTypes, isUnmanaged);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a signature type sufficient here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.Reflection community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants